
#ifndef _MEMBER_BOBJECT_H_
#define _MEMBER_BOBJECT_H_

#include <BMap>
#include <BObject>

#ifdef linux
#include <pthread.h>
#endif

#ifdef _WIN32
#undef APIENTRY
#undef WINGDIAPI
#include <Windows.h>
#include <WinBase.h>
#undef min
#undef max
#endif

#define object_member(object)	((member_BObject*)((BObject*)object)->_ptr)

namespace BWE
{
	class member_BObject
	{
		friend class BObject;

	public:
		class Slot
		{
		public:
			inline Slot()
			{
				object = 0;
				method = 0;
			}
			inline Slot(BObject* object, BObject::slot method)
			{
				this->object = object;
				this->method = method;
			}
			inline Slot(const Slot& other)
			{
				object = other.object;
				method = other.method;
			}

			inline bool operator == (const Slot& other) const
			{
				return object == other.object && method == other.method;
			}
			inline bool operator == (const BObject* object) const
			{
				return this->object == object;
			}

			inline void operator()(const BObject* sender, const BValue& value)
			{
				(object->*method)((BObject*)sender, value);
			}

			BObject*		object;
			BObject::slot	method;
		};
		typedef BArray<Slot>					SlotArray;
		typedef BMap<int, SlotArray>			SigSlotMap;
		typedef BMap<BString, SlotArray>		StrSigSlotMap;

	public:
		member_BObject(BObject* object);
		~member_BObject();
		
		SigSlotMap& globalSigSlotMap();
		StrSigSlotMap& globalStrSigSlotMap();

		bool initMutex();

		template<class METHOD>
		inline bool connect(int signal, METHOD method)
		{
			return boss->attach(signal, (BObject::slot)method);
		}

		template<class METHOD>
		inline bool connect(BObject* object, int signal, METHOD method)
		{
			return boss->attach(object, signal, (BObject::slot)method);
		}

		template<class T>
		inline void check_emit(int signal, const T& value)
		{
			if (boss->checks(signal))
			{
				boss->emit(signal, value);
			}
		}

		void emit(int signal, const BValue& value = BValue());
		void emit(const BString& signal, const BValue& value);
		void post(BObject* receiver, int signal, const BValue& value);
		void post(BObject* receiver, const BString& signal, const BValue& value);

		BObject*				boss;
		BString					name;
		bool					enabled;
		BValue					asset;
		BMap<BString, BValue>	propertyMap;
		BValue					result;
		SigSlotMap				sigSlotMap;
		StrSigSlotMap			strSigSlotMap;
		bool					mutex_initialized;
#ifdef linux
		pthread_mutex_t			mutex;
		int						lockCount = 0;
#else
		CRITICAL_SECTION		criticalSection;
#endif
	};
}

#endif
